/*
 * TcpClientSession.cpp
 *
 *  Created on: Sep 13, 2012
 *      Author: shawnmao
 */

#include "TcpClientSession.h"

TcpClientSession::TcpClientSession(string local_addr,
								   uint16_t local_port,
								   string remote_addr,
								   uint16_t remote_port)
:m_local_addr(inet_addr(local_addr.c_str())),
 m_local_port(htons(local_port)),
 m_remote_addr(inet_addr(remote_addr.c_str())),
 m_remote_port(htons(remote_port))
{
	m_local_struct_addr.sin_family = AF_INET;
	m_local_struct_addr.sin_addr.s_addr = m_local_addr;
	m_local_struct_addr.sin_port = m_local_port;

	m_remote_struct_addr.sin_family = AF_INET;
	m_remote_struct_addr.sin_addr.s_addr = m_remote_addr;
	m_remote_struct_addr.sin_port = m_remote_port;

	m_conn_sock = socket(PF_INET, SOCK_STREAM, 0);
	if(-1 == m_conn_sock) {
		cout<<"Fail to create connected socket "
				"for tcp client session."<<endl;
		m_tcp_state = GILLINGHAM_TCP_CLOSED;
	}
	else {
		m_tcp_state = GILLINGHAM_TCP_SOCKET_CREATED;
	}
}

TcpClientSession::~TcpClientSession()
{
}

int TcpClientSession::cli_connect()
{
	int ret_val;

	if(GILLINGHAM_TCP_SOCKET_CREATED != m_tcp_state) {
		cout<<"The tcp state is not in "
				"GILLINGHAM_TCP_SOCKET_CREATED "
				"when bind to local address."<<endl;
		return -1;
	}

	ret_val = bind(m_conn_sock,
			       (struct sockaddr*)&m_local_struct_addr,
			       sizeof(struct sockaddr));
	if(-1 == ret_val) {
		cout<<"Fail to bind connected socket to local address, "
				"the failure reason is: "<<errno<<endl;
		return -1;
	}
	m_tcp_state = GILLINGHAM_TCP_BOUND;

	ret_val = connect(m_conn_sock,
					  (struct sockaddr*)&m_remote_struct_addr,
					  sizeof(struct sockaddr));
	if(-1 == ret_val) {
		cout<<"Fail to connect to remote host,"
				"the failure reason is: "<<errno<<endl;
		return -1;
	}
	m_tcp_state = GILLINGHAM_TCP_ESTABLISHED;

	return 0;
}

void TcpClientSession::cli_close()
{
	if(GILLINGHAM_TCP_BOUND || GILLINGHAM_TCP_ESTABLISHED == m_tcp_state) {
		close(m_conn_sock);
	}
}
